#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
 
#include "data_type.h"
#include "alloc.h"
#include "memfunc.h"
#include "basefunc.h"
#include "struct_deal.h"
#include "crypto_func.h"
#include "memdb.h"
#include "message.h"
#include "ex_module.h"
#include "return_value.h"
#include "sys_func.h"
#include "tcm_constants.h"
#include "tcm_structures.h"
#include "tcmfunc.h"
#include "tcm_cube_struct.h"
#include "tcm_key_manage.h"
#include "tcm_key_desc.h"
#include "pcr_rw.h"
// add para lib_include
//
int default_index=11;
BYTE Buf[DIGEST_SIZE*16];
int pcr_rw_init(void * sub_proc, void * para)
{
	int ret;
	// Init Tcm Func
	//ret=TCM_LibInit();
	struct init_struct * init_para=para;

	if(para!=NULL)
	{
		default_index=init_para->default_index;
	}	

	// add yorself's module init func here
	return 0;
}

int pcr_rw_start(void * sub_proc, void * para)
{
	int ret;
	void * recv_msg;
	int type;
	int subtype;
	// add yorself's module exec func here

	while(1)
	{
		usleep(time_val.tv_usec);
		ret=ex_module_recvmsg(sub_proc,&recv_msg);
		if(ret<0)
			continue;
		if(recv_msg==NULL)
			continue;
		type=message_get_type(recv_msg);
		subtype=message_get_subtype(recv_msg);
		if(!memdb_find_recordtype(type,subtype))
		{
			printf("message format (%d %d) is not registered!\n",
			message_get_type(recv_msg),message_get_subtype(recv_msg));
			continue;
		}
	
		if((type==TYPE(GENERAL_RETURN))&&(subtype==SUBTYPE(GENERAL_RETURN,BINDATA)))
		{
			ret=proc_pcrrw_bindata_choice(sub_proc,recv_msg);
		}
		else if((type==TYPE(GENERAL_RETURN))&&(subtype==SUBTYPE(GENERAL_RETURN,UUID)))
		{
			ret=proc_pcrrw_uuid_choice(sub_proc,recv_msg);
		}
		else if((type==TYPE(GENERAL_RETURN))&&(subtype==SUBTYPE(GENERAL_RETURN,INT)))
		{
			ret=proc_pcrrw_index_choice(sub_proc,recv_msg);
		}
	}
	return 0;
}

int proc_pcrrw_bindata_choice(void * sub_proc,void * recv_msg)
{
	int ret=0;

	UINT32 result;
	int pcrindex=default_index;
	RECORD(GENERAL_RETURN,BINDATA) *bindata;
	RECORD(GENERAL_RETURN,BINDATA) *outdata;
	void * new_msg;

	int i=0;
	outdata=Talloc0(sizeof(*outdata));
	if(outdata==NULL)
		return -EINVAL;
	outdata->size=DIGEST_SIZE;
	outdata->bindata=Talloc0(DIGEST_SIZE);

	do {
		ret=message_get_record(recv_msg,&bindata,i++);
		if(ret<0)
			return ret;
		if(bindata==NULL)
			break;

		if(Strcmp(bindata->name,"pcrread")==0)
		{
			result=TCM_PcrRead(pcrindex,outdata->bindata);
			if(result!=0)
				return result;
		}
		else if(Strcmp(bindata->name,"extend")==0)
		{
			BYTE digest[DIGEST_SIZE];
			if(bindata->size>0)
			{
				vtcm_ex_sm3(digest,1,bindata->size,bindata->bindata);
				result=TCM_Extend(pcrindex,digest,outdata->bindata);
				if(result!=0)
					return result;
			}
			else	
			{
				result=TCM_PcrRead(pcrindex,outdata->bindata);
				if(result!=0)
					return result;
			}
		}
		else if(Strcmp(bindata->name,"pcrreset")==0)
		{
			result=TCM_PcrReset(pcrindex,outdata->bindata);
			if(result!=0)
				return result;
		}
	}while(1);
	
	new_msg=message_create(TYPE_PAIR(GENERAL_RETURN,BINDATA),recv_msg);
	if(new_msg==NULL)
		return -EINVAL;
	message_add_record(recv_msg,outdata);
	ex_module_sendmsg(sub_proc,new_msg);
	return ret;
}

int proc_pcrrw_uuid_choice(void * sub_proc,void * recv_msg)
{
	int ret=0;

	UINT32 result;
	int pcrindex=default_index;
	RECORD(GENERAL_RETURN,UUID) *bindata;
	RECORD(GENERAL_RETURN,UUID) *outdata;
	void * new_msg;

	int i=0;
	outdata=Talloc0(sizeof(*outdata));
	if(outdata==NULL)
		return -EINVAL;

	do {
		ret=message_get_record(recv_msg,&bindata,i++);
		if(ret<0)
			return ret;
		if(bindata==NULL)
			break;

		if(Strcmp(bindata->name,"pcrread")==0)
		{
			result=TCM_PcrRead(pcrindex,outdata->return_value);
			if(result!=0)
				return result;
		}
		else if(Strcmp(bindata->name,"extend")==0)
		{
			result=TCM_Extend(pcrindex,bindata->return_value,outdata->return_value);
			if(result!=0)
				return result;
		}
		else if(Strcmp(bindata->name,"pcrreset")==0)
		{
			result=TCM_PcrReset(pcrindex,outdata->return_value);
		}
	}while(1);

	new_msg=message_create(TYPE_PAIR(GENERAL_RETURN,UUID),recv_msg);
	if(new_msg==NULL)
		return -EINVAL;
	message_add_record(new_msg,outdata);
	ex_module_sendmsg(sub_proc,new_msg);
	return ret;
}
int proc_pcrrw_index_choice(void * sub_proc,void * recv_msg)
{
	int ret=0;
	int fd;

	UINT32 result;
	int pcrindex=default_index;
	RECORD(GENERAL_RETURN,INT) *bindata;
	void * new_msg;

	ret=message_get_record(recv_msg,&bindata,0);
	if(ret<0)
		return ret;

	if(Strcmp(bindata->name,"default_index")==0)
	{
		default_index=bindata->return_value;
	}
	
	ex_module_sendmsg(sub_proc,recv_msg);
	return ret;
}
